package com.wanhugou.payment.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayFundTransToaccountTransferModel;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.wanhugou.payment.config.AliPayConfig;
import com.wanhugou.payment.domain.PayBizStatusEnum;
import com.wanhugou.payment.domain.PayLog;
import com.wanhugou.payment.domain.PayRecordVo;
import com.wanhugou.payment.domain.PayTypeEnum;
import com.wanhugou.payment.domain.RecordTypeEnum;
import com.wanhugou.payment.service.PayLogService;
import com.wanhugou.payment.util.ParamUtils;
import com.wanhugou.payment.util.ResultData;

@Controller
@RequestMapping("/alipay")
public class AliPayController {
	private static final Logger log = LoggerFactory.getLogger(AliPayController.class);
	
	@Value("${WALLET_URL}")
	private String wallet;
	@Value("${ALI_NOTIFY_URL}")
	private String notifuUrl;
	@Autowired
	private AliPayConfig conf;
	@Autowired
	private PayLogService service;
	@Autowired
	private RestTemplate restTemplate; 
	
	/**
	 * <p>Description: 支付宝转账</br>
	 * @author zhangpf
	 * @param transfer
	 * @throws AlipayApiException
	 */
	@RequestMapping(value = "transfer", method  = RequestMethod.GET)
	@ResponseBody
	public ResultData<PayRecordVo> aliTransfer(@RequestParam("out_trade_no") String out_trade_no,
			@RequestParam("amount") double amount,
			@RequestParam("custId") Integer custId,
			@RequestParam("payer") Integer payer,
			@RequestParam("payee_account") String payee_account) throws AlipayApiException {
		PayLog transfer = new PayLog();
		transfer.setAmount(String.valueOf(amount));
		transfer.setCustId(custId);
		transfer.setPayer(payer);
		transfer.setOut_trade_no(out_trade_no);
		transfer.setPayee_account(payee_account);
		ResultData<PayRecordVo> res = new ResultData<PayRecordVo>();
		AlipayClient alipayClient = conf.getClient();
		AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
		AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
		model.setAmount(transfer.getAmount());
		model.setOutBizNo(transfer.getOut_trade_no());
		model.setRemark(transfer.getRemark());
		model.setPayeeType("ALIPAY_LOGONID");
		model.setPayeeAccount(transfer.getPayee_account());
		model.setPayeeRealName(transfer.getPayee_real_name());
		model.setPayerShowName("北京万户购电子商务有限公司");
		model.setPayeeRealName(transfer.getPayee_real_name());
		request.setBizModel(model);
		//添加提现记录
		transfer.setBiz_status(PayBizStatusEnum.BIZ_STATUS_B.getCode());
		transfer.setPay_type("d");
		transfer.setPlatform("a");
		service.insert(transfer);
		AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
		if(response.isSuccess()){
			String body = response.getBody();
			JSONObject json = JSONObject.fromObject(body);
			JSONObject jsonObject = json.getJSONObject("alipay_fund_trans_toaccount_transfer_response");
			log.debug("<<<调用成功");
			transfer.setBiz_status(PayBizStatusEnum.BIZ_STATUS_C.getCode());
			service.update(transfer);
			//回调钱包
			PayRecordVo vo = new PayRecordVo();
			log.info("支付宝返回数据"+json.toString());
			vo.setAccount(conf.getApp_id());
			vo.setAmount(Double.valueOf(transfer.getAmount()));
			vo.setOutTradeNo(jsonObject.getString("order_id"));
			vo.setPayNum(transfer.getOut_trade_no());//业务单号
			vo.setToAccount(transfer.getPayee_account());
			vo.setRecordType(RecordTypeEnum.WITHDRAWALS.getCode());
			vo.setPayType(PayTypeEnum.PAY_ALIPAY.getCode());
			res.setStatus(res.STATUS_NORMAL);
			res.setData(vo);
		} else {
			log.error("<<<调用失败");
			res.setStatus(res.STATUS_ERROR);
		}
		return res;
	}
	
	@RequestMapping("query/{no}")
	public void query(@PathVariable("no") String no) throws AlipayApiException{
		AlipayClient alipayClient = conf.getClient();
		AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
		AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
		model.setOutBizNo(no);
		request.setBizModel(model);
		AlipayFundTransOrderQueryResponse response = alipayClient.execute(request);
		if(response.isSuccess()){
			System.out.println("调用成功");
		} else {
			System.out.println("调用失败");
		}
	}
	
	/**
	 * 
	 * <p>Description: 支付</br>
	 * @author zhangpf
	 * @param pay
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "pay", method = RequestMethod.GET)
	@ResponseBody
	public ResultData<String> aliPay(@RequestParam("out_trade_no") String out_trade_no,
			@RequestParam("amount") double amount,
			@RequestParam("custId") Integer custId,
			@RequestParam("payer") Integer payer) throws IOException{
		PayLog pay = new PayLog();
		pay.setAmount(String.valueOf(amount));
		pay.setCustId(custId);
		pay.setPayer(payer);
		pay.setOut_trade_no(out_trade_no);
		ResultData<String> res = new ResultData<>();
		AlipayClient alipayClient = conf.getClient();
		//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
		//SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
		model.setBody("充值");
		model.setSubject("北京万户购电子商务有限公司");
		model.setOutTradeNo(pay.getOut_trade_no());
		model.setTimeoutExpress("1m");
		model.setTotalAmount(pay.getAmount());
		model.setProductCode("QUICK_MSECURITY_PAY");
		model.setTimeoutExpress("1m");
		String param = ParamUtils.getParam(pay);
		model.setPassbackParams(param);
		request.setBizModel(model);
		request.setNotifyUrl(notifuUrl);
		try {
	        //这里和普通的接口调用不同，使用的是sdkExecute
	        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
	        if (response.isSuccess()) {
	        	PayLog p = new PayLog();
		        pay.setOut_trade_no(out_trade_no);
		        pay.setAmount(String.valueOf(amount));
				pay.setPlatform("a");
		        pay.setPay_type("a");
		        pay.setBiz_status(PayBizStatusEnum.BIZ_STATUS_B.getCode());
				service.insert(pay);
	        	res.setData(response.getBody());
	        	res.setStatus(res.STATUS_NORMAL);
	        	log.info("请求成功"+res.toString());
			}else{
				res.setData(response.getBody());
	        	res.setStatus(res.STATUS_ERROR);
	        	log.info("请求支付宝失败"+res.toString());
			}
	    } catch (AlipayApiException e) {
	    	res.setStatus(res.STATUS_ERROR);
	    	res.setMessage(e.getErrMsg());
	    	log.error("请求失败"+res.toString());
		}
		return res;
		
	}
	
	/**
	 * 支付宝异步请求通知
	 * @param request
	 * @return
	 * @throws AlipayApiException 
	 */
	@RequestMapping(value = "notify", method = RequestMethod.POST)
	@ResponseBody
	public ResultData<String> notify(HttpServletRequest request) throws AlipayApiException {
		log.info("-------支付宝回调------");
		ResultData<String> res = new ResultData<>();
		//获取支付宝POST过来反馈信息
		Map<String,String> params = new HashMap<String,String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
		    String name = (String) iter.next();
		    String[] values = (String[]) requestParams.get(name);
		    String valueStr = "";
		    for (int i = 0; i < values.length; i++) {
		        valueStr = (i == values.length - 1) ? valueStr + values[i]
		                    : valueStr + values[i] + ",";
		  	}
		    //乱码解决，这段代码在出现乱码时使用。
			//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			params.put(name, valueStr);
		}
		log.info("支付宝返回结果："+params.toString());
		//切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
		//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
		boolean flag = AlipaySignature.rsaCheckV1(params, conf.getAli_public_key(), conf.getCharset(), "RSA2");
	    if(flag){
	        PayLog pay = new PayLog();
	        pay.setOut_trade_no(params.get("out_trade_no"));
	        pay.setBiz_status(PayBizStatusEnum.BIZ_STATUS_C.getCode());
	        String selectByNo = service.selectByNo(params.get("out_trade_no"));
			if (StringUtils.isNotBlank(selectByNo)) {
				service.update(pay);
			}
	        try {
				PayRecordVo vo = appPayCallBack(params);
				ResultData data = restTemplate.postForObject(wallet, vo, ResultData.class);
			} catch (Exception e) {
				e.printStackTrace();
				log.error("请求失败"+e.getMessage());
			}
	    	res.setData("success");
	    	log.debug("<<<支付宝回调成功");
	    }else{
	    	res.setData("fail");
	    	log.error("<<<支付宝回调失败");
	    }
		return res;
	}
	
	private PayRecordVo appPayCallBack(Map<String,String> params) throws Exception{
		PayRecordVo pay = new PayRecordVo();
		pay.setPayNum(params.get("out_trade_no"));	//支付宝交易单号
		pay.setOutTradeNo(params.get("trade_no"));	//系统内部交易单号
		pay.setRecordType(RecordTypeEnum.RECHARGE.getCode());	//充值
		pay.setPayType(PayTypeEnum.PAY_ALIPAY.getCode());	//支付宝
		pay.setAmount(Double.valueOf(params.get("total_amount")));	//总金额
		pay.setAccount(params.get("buyer_logon_id"));	//支付账户
		pay.setToAccount(conf.getApp_id());		//收款账号
		PayLog param = ParamUtils.returnParam(params.get("passback_params"));
		pay.setCustId(param.getCustId());
		pay.setPayer(param.getPayer());
		return pay;
	}
	
	
	
	
}
